package com.esl.coordinator.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author jeffreychang
 * 
 */
public final class CRC {
	static final Logger LOG = LoggerFactory.getLogger(CRC.class);

	public final static String CRC16 = "CRC16";
	public final static String CRC16_Modbus = "CRC16 (Modbus)";
	public final static String CRC16_Sick = "CRC16 (Sick)";
	public final static String CRC16_0x0000 = "CRC-CCITT (0x0000)";
	public final static String CRC16_0xffff = "CRC-CCITT (0xffff)";
	public final static String CRC16_0x1d0f = "CRC-CCITT (0x1d0f)";
	public final static String CRC16_Kermit = "CRC-CCITT (Kermit)";
	public final static String CRC32 = "CRC32";

	private static String TST_CRC_PATH_CMD = "C:/tst_crc.exe -x";

	/**
	 * For CRC values, we run tst_crc.exe written in C and parse the values
	 * 
	 * @param str
	 * @return
	 * @deprecated
	 */
	public static String getCRCCCITT_EXE(String codename, String asciiValue) {
		String output = null;
		try {
			String line = null;
			Process p = Runtime.getRuntime().exec(TST_CRC_PATH_CMD);
			BufferedReader input = new BufferedReader(new InputStreamReader(
					p.getInputStream()));
			PrintWriter out = new PrintWriter(p.getOutputStream());
			out.print(asciiValue);
			out.close();

			String dummy = "= 0x";
			while ((line = input.readLine()) != null) {
				if (line.startsWith(codename)) {
					output = line.substring(
							line.indexOf(dummy) + dummy.length(),
							line.indexOf("/")).trim();
				}
			}
			input.close();
			p.destroy();
		} catch (IOException e) {
			LOG.error("Could not execute CRC windows program.", e);
		}
		return output;
	}

	public static String getCRC_CCITT_Kermit(String str) {
		if (System.getProperty("stiteq.crc.exe") != null) {
			TST_CRC_PATH_CMD = System.getProperty("crc.exe");
			return getCRCCCITT_EXE(CRC16_Kermit, str);
		} else {
			int crc;
			int q;
			byte c;
			crc = 0x00;

			byte[] val = Hex.toHexBytes(str);

			for (int i = 0; i < val.length; i++) {
				c = val[i];
				q = (crc ^ c) & 0x0f;
				crc = (crc >> 4) ^ (q * 0x1081);
				q = (crc ^ (c >> 4)) & 0xf;
				crc = (crc >> 4) ^ (q * 0x1081);
			}
			return Hex.toHexString((crc << 8 | crc >> 8) & 0x0000FFFF);
		}
	}

	public static void main(String[] args) {
		String testStr = "FFFFABABCDCDEFEF";
		LOG.info(getCRCCCITT_EXE(CRC16_Kermit, testStr));
		LOG.info(getCRC_CCITT_Kermit(testStr));
	}
}